package com.woniuxy.redenvelope.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.woniuxy.commons.service.FeignUserService;
import com.woniuxy.redenvelope.exception.RedException;
import com.woniuxy.redenvelope.mapper.KillRedEnvelopeMapper;
import com.woniuxy.redenvelope.mapper.RecordMapper;
import com.woniuxy.redenvelope.service.KillRedEnvelopeSerice;

import com.woniuxy.redenvelope.vo.AddKillVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.ZoneOffset;
import java.util.*;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Service
@Slf4j
public class KillRedEnvelopeServiceImpl implements KillRedEnvelopeSerice {

    @Resource
    private KillRedEnvelopeMapper redEnvelopeMapper;

    @Resource
    private RecordMapper recordMapper;

    @Resource
    private RedisTemplate<String, Object> redisTemplate;


    @Override
    public PageInfo<AddKillVo> findAll(Integer currentPage, Integer pageSize, String name) {
        PageHelper.startPage(currentPage, pageSize);
        List<AddKillVo> list = redEnvelopeMapper.findAll(name);
        PageInfo<AddKillVo> pageInfo = new PageInfo<>(list);
        return pageInfo;
    }

    @Override
    @Transactional
    public boolean add(AddKillVo addKillVo) {
        Date now = new Date();
        //
        if (now.getTime() > addKillVo.getStarttime().getTime()) {
            // 抛异常

        }
        // MySQL数据只做活动的记录
        redEnvelopeMapper.add(addKillVo);

        // Redis中做秒杀的具体的业务
        long time = addKillVo.getStarttime().getTime() - now.getTime();
        // 判断开始时间与当前时间的差距
        log.info("time:{}", time);
        long flag = 0;
        if (time <= flag) {
            redisTemplate.opsForHash().put("kill", addKillVo.getId() + "", addKillVo);
            // 结束时间移出redis
            removeKill(addKillVo);
            // 验证存储在redis中的对象
            Object o = redisTemplate.opsForHash().get("kill", addKillVo.getId() + "");
            log.info("红包状态更新为进行中: {}", o);
        } else if (time - flag == 0) {
            addKillVo.setState("进行中");
        } else {
            addKillVo.setState("未开始");
            redisTemplate.opsForValue().set("kill_start_" + addKillVo.getId(), addKillVo, time - flag, TimeUnit.MILLISECONDS);
            log.info("红包状态更新为未开始");
        }
        return false;
    }

    @Override
    public boolean edit(AddKillVo addKillVo) {
        return redEnvelopeMapper.edit(addKillVo);
    }

    @Override
    public boolean delete(Integer id) {
        return redEnvelopeMapper.delete(id);
    }

    @Override
    public void addKillToRedis(Integer kid) {
        // 通过kid拿到秒杀信息，放入redis
        AddKillVo addKillVo = redEnvelopeMapper.findById(kid);
        redisTemplate.opsForHash().put("kill", String.valueOf(addKillVo.getId()), addKillVo);
        removeKill(addKillVo);
    }

    @Override
    public void removeKillFromRedis(Integer kid) {
        redisTemplate.opsForHash().delete("kill", String.valueOf(kid));
    }

    // 定时移除秒杀活动
    public void removeKill(AddKillVo addKillVo) {
        Date date = new Date();
        long time = addKillVo.getEndtime().getTime() - date.getTime();
        redisTemplate.opsForValue().set("kill_end_" + addKillVo.getId(), null, time, TimeUnit.MILLISECONDS);
    }

/*    @Override
    public List<AddKillVo> list() {

        // 从redis中获取所有秒杀活动
        Map<Object, Object> killMap = redisTemplate.opsForHash().entries("kill");
        //
        List<AddKillVo> data = new ArrayList<>();
        // 遍历信息封装红包
        Iterator<Object> iterator = killMap.keySet().iterator();
        while (iterator.hasNext()){
            String key = (String)iterator.next();
            AddKillVo addKillVo = (AddKillVo) killMap.get(key);
            data.add(addKillVo);
        }
        return data;
    }*/

    @Override
    // synchronized 锁，锁住当前对象
    public synchronized boolean pay(Integer rid) {
        // 先从redis中获取秒杀信息
        AddKillVo addKillVo1 = (AddKillVo) redisTemplate.opsForHash().get("kill", String.valueOf(rid));
        // 用redis中得到用户id
        Integer uid = addKillVo1.getUid();
        // 判断剩余数量是否大于0
        if (addKillVo1.getNum() == 0) {
            throw new RedException("红包已空");
        } else if (redEnvelopeMapper.existsByUidAndPid(uid, rid)) {
            throw new RedException("您已经抢过红包了");
        } else {
            // 删减数量
            addKillVo1.setNum(addKillVo1.getNum() - 1);
            // 更新redis
            redisTemplate.opsForHash().put("kill", String.valueOf(rid), addKillVo1);
            log.info("剩余数量: {}", addKillVo1.getNum());
            // 红包详情表插入数据
            redEnvelopeMapper.addkill(addKillVo1);

            //将红包放进redis中定时7天
            // 将红包详情放入 Redis，并设置过期时间为 7 天
            String recordKey = "redtime_" + addKillVo1.getId();
            redisTemplate.opsForValue().set(recordKey, addKillVo1, 7, TimeUnit.DAYS);
            return true;
        }
    }

    @Override
    public PageInfo<AddKillVo> getKillRedEnvelope(Integer currentPage, Integer pageSize, String name) {
        PageHelper.startPage(currentPage, pageSize);
        List<AddKillVo> list = redEnvelopeMapper.getKillRedEnvelope(name);
        PageInfo<AddKillVo> pageInfo = new PageInfo<>(list);
        return pageInfo;
    }

    // 编辑还未开始的红包
    @Override
    public boolean editKillRedEnvelope(AddKillVo addKillVo) {
        Date now = new Date();
        // 拿到redis还没开始的红包信息
        Object o = redisTemplate.opsForValue().get("kill_start_" + addKillVo.getId());
        // 将其从redis中移除
        redisTemplate.delete("kill_start_" + addKillVo.getId());
        // 重新存入新的红包信息
        // Redis中做秒杀的具体的业务
        long time = addKillVo.getStarttime().getTime() - now.getTime();
        // 判断开始时间与当前时间的差距
        log.info("time:{}", time);
        long flag = 0;
        // 更改状态未开始
        redEnvelopeMapper.updateStatus(addKillVo.getId(), "未开始");
        if (time <= flag) {
            redisTemplate.opsForHash().put("kill", addKillVo.getId() + "", addKillVo);
            // 结束时间移出redis
            removeKill(addKillVo);
            // 验证存储在redis中的对象
            Object o1 = redisTemplate.opsForHash().get("kill", addKillVo.getId() + "");
            log.info("红包状态更新为进行中: {}", o1);
        } else {
            addKillVo.setState("未开始");
            redisTemplate.opsForValue().set("kill_start_" + addKillVo.getId(), addKillVo, time - flag, TimeUnit.MILLISECONDS);
            log.info("红包状态更新为未开始");
        }
        //redisTemplate.opsForValue().set("kill_start_" + addKillVo.getId(), addKillVo, time - flag, TimeUnit.MILLISECONDS);
        return redEnvelopeMapper.editKillRedEnvelope(addKillVo);
    }

    @Override
    // 随时停止还没进行的红包
    public boolean stopKillFromRedis(Integer id) {
        // 拿到红包信息
        Object o = redisTemplate.opsForValue().get("kill_start_" + id);
        // 移除
        redisTemplate.delete("kill_start_" + id);
        // 更新状态
        redEnvelopeMapper.updateStatus(id, "已停止");
        log.info("红包状态更新为已停止");

        return true;


    }


}
